/***************************************************************************
 *    
 *      Copyright (c) 2009,2010 KaiTrade LLC (registered in Delaware)
 *                     All Rights Reserved Worldwide
 *
 * STRICTLY PROPRIETARY and CONFIDENTIAL
 *
 * WARNING:  This file is the confidential property of KaiTrade LLC For
 * use only by those with the express written permission and license from
 * KaiTrade LLC.  Unauthorized reproduction, distribution, use or disclosure 
 * of this file or any program (or document) is prohibited. 
 * 
 ***************************************************************************/
using System;
using System.Collections.Generic;
using System.Text;

namespace K2AlgoSet
{
    public enum CrossType
    {
        Up, Down, Undefined            
    }
    public enum ValPosition
    {
        above, below, Undefined
    }
    /// <summary>
    /// Detect crossovers between curves and bar data
    /// </summary>
    public class CrossDetect : PatternMatchBase
    {
        
        private string m_Val1Name = "";
        private double m_Val1 = 0.0;
        private double m_Val1Prev = 0.0;
        private double m_Val1XOver = 0.0;
        private ValPosition m_Val1PrevPos = ValPosition.Undefined;

        private string m_Val2Name = "";
        private double m_Val2 = 0.0;
        private double m_Val2Prev = 0.0;
        private double m_Val2XOver = 0.0;

        private double m_Delta = 0.0;
        private double m_DeltaThreashold = 0.2;

        private double m_ATRValue = 0.0;
        private bool m_UseAtrInhibit = false;
        private double m_ATRHiLimit = 0.0;
        private double m_ATRLowLimit = 0.0;
        private string m_ATRCurveName = "";

        private CrossType m_CrossType;

        

        public  CrossDetect()
        {
            m_Name = "CrossDetect";
            
            m_Log.Info("CrossDetect");
            m_CrossType = CrossType.Undefined;
            m_Output = new double[2];
            m_Output[0] = -1;
            m_Output[1] = -1;
        }

        public override string ToString()
        {
            string myRet = "CrossDetect:,";
            myRet += m_Val1Name.ToString() + ",";
            myRet += m_Val1.ToString() + ",";
            myRet += m_Val1Prev.ToString() + ",";
            myRet += m_Val1XOver.ToString() + ",";
            myRet += m_Val2Name.ToString() + ",";
            myRet += m_Val2.ToString() + ",";
            myRet += m_Val2Prev.ToString() + ",";
            myRet += m_Val2XOver.ToString() + ",";
            myRet += m_Delta.ToString() + ",";
            myRet += m_Output[0].ToString() + ",";
            myRet += m_Output[1].ToString() ;



           
            return myRet;

            //return string.Format("Customer = {0} ID = {1}", Customer, CustomerID);
        }

        protected override void parseParameters()
        {
            try
            {
                string[] myParms = m_ParameterString.Split(',');
                if (myParms.Length < 3)
                {
                    m_Log.Error("Must specified curvenames and delta:" + m_ParameterString);
                    return;
                }
                m_Val1Name = myParms[0];
                m_Val2Name = myParms[1];
                m_DeltaThreashold = double.Parse(myParms[2]);
                if(myParms.Length >=6)
                {
                    // can do ATR inhibit processing
                    m_UseAtrInhibit = true;
                    m_ATRCurveName = myParms[3];
                    m_ATRLowLimit = double.Parse(myParms[4]);
                    m_ATRHiLimit = double.Parse(myParms[5]);
                }
                
            }
            catch (Exception myE)
            {
                m_Log.Error("getData", myE);
            }
        }

        

        

        private void getData()
        {
            try
            {
                m_Val1 = m_TSSet.CurrentItem.GetCurveValue(m_Val1Name);
                m_Val2 = m_TSSet.CurrentItem.GetCurveValue(m_Val2Name);
                m_Val1Prev = m_TSSet.CurrentItem.GetPrevCurveValue(m_Val1Name);   
                m_Val2Prev = m_TSSet.CurrentItem.GetPrevCurveValue(m_Val2Name);
                if (m_UseAtrInhibit)
                {
                    m_ATRValue = m_TSSet.CurrentItem.GetCurveValue(m_ATRCurveName);
                }
            }
            catch (Exception myE)
            {
                //m_Log.Error("getData", myE);
            }
        }

        private bool isInAtrLimits()
        {
            if (m_UseAtrInhibit)
            {
                if ((m_ATRValue >= m_ATRLowLimit) && (m_ATRValue <= m_ATRHiLimit))
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                return true;
            }
        }

        /// <summary>
        /// Detect matches in the set associated with the matcher - this will
        /// typically set/publish conditions
        /// </summary>
        public override void DetectMatches(bool isAdded)
        {
            try
            {
                // Get data current and previous values
                getData();

                // Detect a Val1 up through Val2 crossover
                if (m_Val1 > m_Val2)
                {
                    m_Delta = m_Val1 - m_Val2;

                    // Identify the cross up
                    if (m_Val1PrevPos == ValPosition.below)
                    {
                        if (m_CrossType != CrossType.Up)
                        {
                            m_Output[0] = -1;

                            m_Val1XOver = m_Val1;
                            m_Val2XOver = m_Val2;
                            m_CrossType = CrossType.Up;
                            string myInfo = string.Format("CrossDetect: Cross UP Detected:" + m_Val1Name + ":" + m_Val2Name);
                            
                            m_Log.Info(myInfo);
                            m_Log.Info("THIS:"+this.ToString());
                            m_Log.Info("BAR:"+m_TSSet.CurrentItem.ToString());
                        }
                    }

                    // Apply the delta test
                    if (m_CrossType == CrossType.Up)
                    {
                        m_Delta = m_Val1 - m_Val2XOver;
                        if (m_Delta >= m_DeltaThreashold)
                        {
                            if (m_Output[0] != 1)
                            {
                                setResults();
                            }
                        }
                    }
                    m_Val1PrevPos = ValPosition.above;

                }
                if (m_Val1 < m_Val2)
                {
                    
                    if (m_Val1PrevPos == ValPosition.above)
                    {
                        m_Delta = m_Val2 - m_Val1;

                        if (m_CrossType != CrossType.Down)
                        {
                            m_Output[1] = -1;
                            m_Val1XOver = m_Val1;
                            m_Val2XOver = m_Val2;
                            m_CrossType = CrossType.Down;
                            string myInfo = string.Format("CrossDetect: Cross DOWN Detected:" + m_Val1Name + ":" + m_Val2Name);
                            m_Log.Info(myInfo);
                            m_Log.Info("THIS:" + this.ToString());
                            m_Log.Info("BAR:" + m_TSSet.CurrentItem.ToString());
                        }
                    }
                    if (m_CrossType == CrossType.Down)
                    {
                        m_Delta = m_Val2XOver-m_Val1;
                        if (m_Delta >= m_DeltaThreashold)
                        {
                            //string myInfo = string.Format("CrossDetect: About to set results:" + m_Val1Name + ":" + m_Val2Name);
                            //m_Log.Info(myInfo);
                            if (m_Output[1] != 1)
                            {
                                setResults();
                            }
                        }
                    }
                    m_Val1PrevPos = ValPosition.below;
                }
            }
            catch (Exception myE)
            {
                m_Log.Error("DetectMatches", myE);
            }
        }

        private void setResults()
        {
            try
            {
                if (this.isInAtrLimits())
                {
                    if (m_CrossType == CrossType.Up)
                    {
                        m_Output[0] = 1;
                        m_Output[1] = 0;
                        SetTriggerResults("DN", false);
                        SetTriggerResults("UP", true);


                        string myInfo = string.Format("CrossDetect: SetResults: Pub {0} TriggerName {1} TriggerState {2} ", m_PublishName, m_Alias + "UP", "true");
                        m_Log.Info(myInfo);
                        m_Log.Info("THIS:" + this.ToString());
                        m_Log.Info("BAR:" + m_TSSet.CurrentItem.ToString());
                    }
                    else
                    {
                        m_Output[0] = 0;
                        m_Output[1] = 1;
                        SetTriggerResults("UP", false);
                        SetTriggerResults("DN", true);

                        string myInfo = string.Format("CrossDetect: SetResults: Pub {0} TriggerName {1} TriggerState {2} ", m_PublishName, m_Alias + "DN", "true");
                        m_Log.Info(myInfo);
                        m_Log.Info("THIS:" + this.ToString());
                        m_Log.Info("BAR:" + m_TSSet.CurrentItem.ToString());
                    }
                }

            }
            catch (Exception myE)
            {
                m_Log.Error("setResults", myE);
            }
        }
        
        /// <summary>
        /// Get a list of the trigger names the pattern matcher publishes - if any
        /// </summary>
        public override List<string> TriggerNames
        {
            get
            {
                List<string> myRet = new List<string>();
                myRet.Add(m_Alias + "UP");
                myRet.Add(m_Alias + "DN");
                return myRet;
            }
        }
    }
}
